package com.mybatis.jpa.sqlbuilder.query.parser;

import com.mybatis.jpa.sqlbuilder.query.condition.Condition;
import com.mybatis.jpa.sqlbuilder.query.condition.ConditionParam;
import com.mybatis.jpa.sqlbuilder.query.condition.Equals;
import com.mybatis.jpa.sqlbuilder.query.condition.GreaterThan;
import com.mybatis.jpa.sqlbuilder.query.condition.GreaterThanEqual;
import com.mybatis.jpa.sqlbuilder.query.condition.In;
import com.mybatis.jpa.sqlbuilder.query.condition.LessThan;
import com.mybatis.jpa.sqlbuilder.query.condition.LessThanEqual;
import com.mybatis.jpa.utils.FieldFacade;
import com.mybatis.jpa.utils.ObjectFacade;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class Part {

    private static Map<Type, Condition> map = new HashMap<>();
    private Condition condition;
    private ConditionParam param;

    static {
        map.put(Type.LESS_THAN, new LessThan());
        map.put(Type.LESS_THAN_EQUAL, new LessThanEqual());
        map.put(Type.GREATER_THAN, new GreaterThan());
        map.put(Type.GREATER_THAN_EQUAL, new GreaterThanEqual());
        map.put(Type.IN, new In());
        map.put(Type.SIMPLE_PROPERTY, new Equals());
    }

    public Part(String source, Class entityClass, String paramKey, Map<String, Object> paramMap) {
        ObjectFacade objectFacade = new ObjectFacade(entityClass);
        String partToUse = Type.extractProperty(source);
        Type type = Type.fromProperty(source);
        FieldFacade ff = objectFacade.getFiledFacade(partToUse);
        String columnName = ff.getColumnName();
        String fileName = ff.getField().getName();

        param = new ConditionParam(columnName, fileName, paramKey, paramMap);
        condition = map.get(type);
    }

    public String getSqlCondition() {
        return condition.getPart(param);
    }

    private enum  Type {
        LESS_THAN("LessThan"),
        LESS_THAN_EQUAL("LessThanEqual"),
        GREATER_THAN("GreaterThan"),
        GREATER_THAN_EQUAL("GreaterThanEqual"),
        IN("In"),
        SIMPLE_PROPERTY("Equals");

        private static List<Type> ALL = Arrays.asList(LESS_THAN, LESS_THAN_EQUAL, GREATER_THAN, GREATER_THAN_EQUAL, IN, SIMPLE_PROPERTY);
        public String key;
        Type (String key) {
            this.key = key;
        }

        public static Type fromProperty(String rawProperty) {
            Iterator<Type> iterator = ALL.iterator();
            Type type;
            do {
                if (!iterator.hasNext()) {
                    // 规则全部不匹配，使用默认值
                    return SIMPLE_PROPERTY;
                }

                type = iterator.next();
            } while(!type.supports(rawProperty));
            return type;
        }

        /**
         * 过滤关键字，获取对象属性名字
         * @param part
         * @return
         */
        public static String extractProperty(String part) {
            Iterator<Type> iterator = ALL.iterator();

            String keyword;
            do {
                if (!iterator.hasNext()) {
                    return part;
                }

                keyword = iterator.next().key;
            } while(!part.endsWith(keyword));

            return part.substring(0, part.length() - keyword.length());
        }

        private boolean supports(String rawProperty) {
            return rawProperty.endsWith(key);
        }
    }
}
